package com.kuang.volatiledemo;

import java.util.concurrent.ForkJoinPool;

/**
 * volatile :
 *      1.保证可见性
 *      2.不保证原子性
 *      3.禁止指令重排
 *
 * 验证2：不保证原子性
 *      原子性：不可分割，线程A在执行任务的时候，不能被打扰，也不能被分割，要么同时成功，要么同时失败。
 *      sychronized、Lock锁可以保证原子性
 * 问题：
 *      如果不加sychronized、Lock锁，怎么可以保证原子性?
 *      使用原子类解决  AtomicInteger num   Demo3
 *
 */
public class Demo2 {

    //private static int num = 0;
    private static volatile int num = 0;

    // volatile 不保证原子性
    public static void add(){
        num ++; //不是一个原子性操作
        // 底层多步骤操作，多个线程进来时，就会有是否原子性操作问题
        // 打开字节码文件，cmd进入，javap -c 分析
        // 1. getstatic  获取这个值
        // 2. iconst_l   常量i
        // 3. i+1
        // 4. putstatic  写回这个值
    }

    // synchronized 保证原子性
    public static synchronized void add1(){
        num ++;
    }

    public static void main(String[] args) {
        // 创建20个线程，每个线程执行1000次，预期得到结果2w
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                for (int j = 0; j < 1000; j++) {
                    add();  // main 19383
                    //add1();   //main 20000
                }
            }).start();
        }

        // 主线程
        // 判定执行：如果活跃的线程数>2,主线程和垃圾回收线程礼让，让其余线程先执行
        // 默认执行线程：main  gc
        while (Thread.activeCount() > 2){
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName() + " " +num);
    }
}
